package org.sas.example.authentication.wechat;

import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;

import java.util.Arrays;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * 第一步
 * 自定义微信登录授权申请接口携带的参数
 * 微信用户同意授权，获取code文档中，参数列表里有一个appid的参数，这个参数的意思是跟client_id是一样的，但是名字是叫appid，
 * 如果直接用OAuth2 Client根据这些参数登录的话是走不下去的，因为OAuth2 Client不会带appid参数，只会带client_id参数，
 * 所以这时候就要在跳转至请求授权页面之前修改授权申请的参数。
 * <a href="https://docs.spring.io/spring-security/reference/servlet/oauth2/client/authorization-grants.html#_customizing_the_authorization_request">有关文档</a>
 * @see DefaultOAuth2AuthorizationRequestResolver#setAuthorizationRequestCustomizer(Consumer)
 * @author LiJY
 * @date 2024/07/11
 */
public class WechatAuthorizationRequestConsumer implements Consumer<OAuth2AuthorizationRequest.Builder> {

    /**
     * 默认情况下Spring Security会生成授权链接：
     * {@code https://open.weixin.qq.com/connect/oauth2/authorize?response_type=code
     * &client_id=wxdf9033184b238e7f
     * &scope=snsapi_userinfo
     * &state=5NDiQTMa9ykk7SNQ5-OIJDbIy9RLaEVzv3mdlj8TjuE%3D
     * &redirect_uri=https%3A%2F%2Fmov-h5-test.felord.cn}
     * 缺少了微信协议要求的{@code #wechat_redirect}，同时 {@code client_id}应该替换为{@code app_id}
     *
     *
     * @param builder builder
     */
    @Override
    public void accept(OAuth2AuthorizationRequest.Builder builder) {
        builder.attributes(attributes ->
                Arrays.stream(ClientProviders.values())
                        .filter(clientProvider ->
                                Objects.equals(clientProvider.registrationId(),
                                        attributes.get(OAuth2ParameterNames.REGISTRATION_ID)))
                        .findAny()
                        .map(ClientProviders::requestConsumer)
                        .ifPresent(requestConsumer ->
                                requestConsumer.accept(builder)));
    }

}
